<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<title>AR</title>

	<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<script src="./build/three.min.js"></script>
	<!-- <script src="./build/three.js"></script> -->
	<script src="./build/ar.js"></script>

	<script src="./build/spdLoader.js"></script>

</head>

<body>
	<script>
		let renderer = new THREE.WebGLRenderer({
			antialias: true,
			alpha: true
		});
		renderer.setClearColor(new THREE.Color('lightgrey'), 0)
		renderer.setSize(640, 480);
		renderer.domElement.style.position = 'absolute'
		renderer.domElement.style.top = '0px'
		renderer.domElement.style.left = '0px'
		document.body.appendChild(renderer.domElement);

		// array of functions for the rendering loop
		let onRenderFcts = [];

		// init scene and camera
		let scene = new THREE.Scene();

		//////////////////////////////////////////////////////////////////////////////////
		//		Initialize a basic camera
		//////////////////////////////////////////////////////////////////////////////////

		// Create a camera
		let camera = new THREE.Camera();
		scene.add(camera);

		scene.add(new THREE.AmbientLight(0x222222));
		pointLight = new THREE.PointLight(0xffffff, 1.0);//点光源
		pointLight.position.copy(camera.position);
		camera.add(pointLight);
		////////////////////////////////////////////////////////////////////////////////
		//          handle arToolkitSource
		////////////////////////////////////////////////////////////////////////////////

		let arToolkitSource = new THREEx.ArToolkitSource({
			// to read from the webcam
			sourceType: 'webcam',

			// // to read from an image
			// sourceType : 'image',
			// sourceUrl : THREEx.ArToolkitContext.baseURL + '../data/images/img.jpg',

			// to read from a video
			// sourceType : 'video',
			// sourceUrl : THREEx.ArToolkitContext.baseURL + '../data/videos/headtracking.mp4',
		})

		arToolkitSource.init(function onReady() {
			setTimeout(() => {
				onResize()
			}, 2000);
		})

		// handle resize
		window.addEventListener('resize', function () {
			onResize()
		})

		function onResize() {
			arToolkitSource.onResizeElement()
			arToolkitSource.copyElementSizeTo(renderer.domElement)
			if (arToolkitContext.arController !== null) {
				arToolkitSource.copyElementSizeTo(arToolkitContext.arController.canvas)
			}
		}
		////////////////////////////////////////////////////////////////////////////////
		//          initialize arToolkitContext
		////////////////////////////////////////////////////////////////////////////////


		// create atToolkitContext
		let arToolkitContext = new THREEx.ArToolkitContext({
			cameraParametersUrl: './data/camera_para.dat',
			detectionMode: 'mono',
		})
		// initialize it
		arToolkitContext.init(function onCompleted() {
			// copy projection matrix to camera
			camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix());
		})

		// update artoolkit on every frame
		onRenderFcts.push(function () {
			if (arToolkitSource.ready === false) return

			arToolkitContext.update(arToolkitSource.domElement)

			// update scene.visible if the marker is seen
			scene.visible = camera.visible
		})

		////////////////////////////////////////////////////////////////////////////////
		//          Create a ArMarkerControls
		////////////////////////////////////////////////////////////////////////////////

		// init controls for camera
		let markerControls = new THREEx.ArMarkerControls(arToolkitContext, camera, {
			type: 'pattern',
			// patternUrl: '../../data/ardata/HZ_pattern-marker.patt',
			patternUrl: './data/pattern-hz.patt',
			// patternUrl : THREEx.ArToolkitContext.baseURL + '../data/data/patt.kanji',
			// as we controls the camera, set changeMatrixMode: 'cameraTransformMatrix'
			changeMatrixMode: 'cameraTransformMatrix'
		})
		// as we do changeMatrixMode: 'cameraTransformMatrix', start with invisible scene
		scene.visible = false

		//////////////////////////////////////////////////////////////////////////////////
		//		add an object in the scene
		//////////////////////////////////////////////////////////////////////////////////

		// add a torus knot
		let geometry = new THREE.CubeGeometry(1, 1, 1);
		let bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);
		let material = new THREE.MeshPhongMaterial({
			transparent: true,
			opacity: 0.5,
			// side: THREE.DoubleSide
		});
		let mesh = new THREE.Mesh(bufferGeometry, material);
		mesh.position.y = geometry.parameters.height / 2;

		// scene.add(mesh);


		let group3d = new THREE.Group();
		
		window.addEventListener('message', (e) => {
			let data = e.data;
			switch (data.cmd) {
				case 'setGeoBlobData':
					let geoDataLst = data.blobdata;
					let spdLoader = new S3DVL.SpdJSONLoader();
					for (let index = 0; index < geoDataLst.length; index++) {
						let element = geoDataLst[index];
						let jsonObj = JSON.parse(element);
						let spdmetadata = jsonObj.metaData;
						if (spdmetadata !== undefined) {
							let formatType = spdmetadata.formatType;

							switch (formatType) {
								case 'SPD DIMENSION':
									let spdDObject = spdLoader.parseDM(jsonObj.dimensions);
									for (let index = 0; index < spdDObject.length; index++) {
										let element = spdDObject[index];
										group3d.add(element);
									}
									break;
								case 'SPD GEOMETRY':
									let spdGObject = spdLoader.parse(jsonObj.parts);
									for (let index = 0; index < spdGObject.length; index++) {
										let element = spdGObject[index];
										group3d.add(element);
									}
									break;
								default:
									break;
							}
						}
					}
					let axis = new THREE.Vector3(1, 0, 0);
					let rotWorldMatrix = new THREE.Matrix4();
					rotWorldMatrix.elements = camera.projectionMatrix;
					rotWorldMatrix.makeRotationAxis(axis.normalize(), 90 * Math.PI / 180);
					group3d.matrix = rotWorldMatrix;
					group3d.rotation.setFromRotationMatrix(group3d.matrix);
					group3d.scale.set(0.001, 0.001, 0.001);
					let boundingBoxOfNode = new THREE.Box3().setFromObject(group3d);
					let centerOfGravity = new THREE.Vector3();
					//centerOfGravity = boundingBoxOfNode.getCenter(centerOfGravity);
					let sizex = boundingBoxOfNode.max.x - boundingBoxOfNode.min.x;
					let sizey = boundingBoxOfNode.max.y - boundingBoxOfNode.min.y;
					let sizez = boundingBoxOfNode.max.z - boundingBoxOfNode.min.z;
					group3d.position.x = -boundingBoxOfNode.min.x - sizex / 2;
					group3d.position.y = -boundingBoxOfNode.min.y - sizey / 2;
					group3d.position.z = -boundingBoxOfNode.min.z - sizez / 2;
					//

					group3d.updateMatrix();
					scene.add(group3d);
					break;
			}  //e.data为传递过来的数据 //e.source为对发送消息的窗口对象的引用，可以使用此来在具有不同origin的两个窗口之间建立双向通信
		}, false);

		//////////////////////////////////////////////////////////////////////////////////
		//		render the whole thing on the page
		//////////////////////////////////////////////////////////////////////////////////

		// render the scene
		onRenderFcts.push(function () {
			renderer.render(scene, camera);
		})

		// run the rendering loop
		let lastTimeMsec = null
		requestAnimationFrame(function animate(nowMsec) {
			// keep looping
			requestAnimationFrame(animate);
			// measure time
			lastTimeMsec = lastTimeMsec || nowMsec - 1000 / 60
			let deltaMsec = Math.min(200, nowMsec - lastTimeMsec)
			lastTimeMsec = nowMsec
			// call each update function
			onRenderFcts.forEach(function (onRenderFct) {
				onRenderFct(deltaMsec / 1000, nowMsec / 1000)
			})
		})


	</script>
</body>

</html>